<template>
  <div class="quill-editor">
    <div ref="editorContainer"></div>
    <input ref="imageInput" type="file" hidden accept="image/*" @change="handleImageUpload" />
  </div>
</template>

<script setup lang="ts">
import 'quill/dist/quill.snow.css';

import Quill from 'quill';
import { onMounted, ref, watch } from 'vue';

import { request } from '@/utils/request';

const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  uploadUrl: {
    type: String,
    default: '/upload',
  },
  maxSize: {
    type: Number,
    default: 5, // 单位MB
  },
});

const emit = defineEmits(['update:modelValue', 'upload-error']);

const editorContainer = ref<HTMLElement>();
const imageInput = ref<HTMLInputElement>();
let quill: Quill | null = null;

// 初始化编辑器
onMounted(() => {
  if (!editorContainer.value) return;

  const toolbarOptions = [
    [{ size: ['small', false, 'large', 'huge'] }],
    [{ header: [1, 2, 3, false] }],
    ['bold', 'italic', 'underline', 'blockquote'],
    [{ list: 'ordered' }, { list: 'bullet' }],
    ['blockquote', 'code-block'],
    ['link', 'image'],
    ['clean'],
  ];
  quill = new Quill(editorContainer.value, {
    theme: 'snow',
    modules: {
      toolbar: {
        container: toolbarOptions,
        handlers: {
          image: () => imageInput.value?.click(), // 接管图片上传[3]()
        },
      },
    },
  });

  // 初始化内容
  quill.root.innerHTML = props.modelValue;

  // 内容变更事件
  quill.on('text-change', () => {
    const html = quill?.root.innerHTML || '';
    emit('update:modelValue', html);
  });
});

// 图片上传处理
const handleImageUpload = async (e: Event) => {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (!file) return;

  try {
    // 文件校验
    if (file.size > props.maxSize * 1024 * 1024) {
      throw new Error(`图片大小不能超过${props.maxSize}MB`);
    }

    // 插入占位图
    const range = quill?.getSelection()?.index;
    if (typeof range !== 'number') return;
    quill?.insertEmbed(range, 'image', '/loading.gif');
    quill?.setSelection(range + 1);

    const { url } = await request.upload('file', file, { url: props.uploadUrl });

    // 替换真实URL
    quill?.deleteText(range, 1);
    quill?.insertEmbed(range, 'image', url);
  } catch (error) {
    emit('upload-error', error);
    quill?.deleteText(range!, 1); // 回滚占位图[5]()
  } finally {
    if (imageInput.value) imageInput.value.value = '';
  }
};

// 双向绑定同步
watch(
  () => props.modelValue,
  (newVal) => {
    if (newVal !== quill?.root.innerHTML) {
      quill?.clipboard.dangerouslyPasteHTML(newVal);
    }
  },
);
</script>

<style scoped>
.quill-editor {
  background: white;
}
:deep(.ql-editor) {
  min-height: 300px;
}
</style>
